/**
 * $Revision: 1.1 $
 * $Date: 2010/06/28 07:03:25 $
 *
 * Copyright (C) 2006 Jive Software. All rights reserved.
 *
 * This software is published under the terms of the GNU Lesser Public License (LGPL),
 * a copy of which is included in this distribution.
 */

package cn.newgrand.netcall.ui.questionRecord;

import org.jivesoftware.Spark;
import org.jivesoftware.resource.Res;
import org.jivesoftware.resource.SparkRes;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.component.FileDragLabel;
import org.jivesoftware.spark.ui.ContactItem;
import org.jivesoftware.spark.ui.ContactList;
import org.jivesoftware.spark.util.ByteFormat;
import org.jivesoftware.spark.util.GraphicUtils;
import org.jivesoftware.spark.util.SwingWorker;
import org.jivesoftware.spark.util.log.Log;

import cn.newgrand.smackx.attachmenttransfer.FileTransfer;
import cn.newgrand.smackx.attachmenttransfer.FileTransfer.Status;
import cn.newgrand.smackx.attachmenttransfer.FileTransferManager;
import cn.newgrand.smackx.attachmenttransfer.OutgoingFileTransfer;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;

public class AttachmentDisplayPanel extends JPanel {
	private static final long serialVersionUID = 1L;
	private FileDragLabel imageLabel = new FileDragLabel();
    private JLabel titleLabel = new JLabel();
    private JLabel fileLabel = new JLabel();
    
    private String questionRecordId;

    private TransferButton deleteButton = new TransferButton();
    private TransferButton cancelButton = new TransferButton();
    private TransferButton uploadButton = new TransferButton();
    private JProgressBar progressBar = new JProgressBar();
    private File fileToSend;
    private OutgoingFileTransfer transfer;


    private TransferButton retryButton = new TransferButton();

    private String nickname;

    public AttachmentDisplayPanel(final File file,final AttachmentContainer attachContainer,String questionRecordId,final OutgoingFileTransfer outTransfer) {
        setLayout(new GridBagLayout());
        
        fileToSend = file;
        this.questionRecordId = questionRecordId;

        setBackground(new Color(250, 249, 242));
        add(imageLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
        add(fileLabel, new GridBagConstraints(1, 1, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0));
        
        deleteButton.setText("删除");
        cancelButton.setText("取消");
        uploadButton.setText("上传");
        
        cancelButton.setVisible(false);
        titleLabel.setVisible(false);

        add(deleteButton, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));
        add(cancelButton, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));
        add(titleLabel, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));
        
        titleLabel.setForeground(new Color(73, 113, 196));
        titleLabel.setFont(new Font("Dialog", Font.BOLD, 12));
        titleLabel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196)));
        
        cancelButton.setForeground(new Color(73, 113, 196));
        cancelButton.setFont(new Font("Dialog", Font.BOLD, 12));
        cancelButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196)));
        
        deleteButton.setForeground(new Color(73, 113, 196));
        deleteButton.setFont(new Font("Dialog", Font.BOLD, 12));
        deleteButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196)));
        add(uploadButton, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));

        uploadButton.setForeground(new Color(73, 113, 196));
        uploadButton.setFont(new Font("Dialog", Font.BOLD, 12));
        uploadButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196)));
        
        deleteButton.addMouseListener(new MouseAdapter() {
        	public void mouseClicked(MouseEvent mouseEvent) {
                attachContainer.removeComponent(file.getName());
            }
        	
            public void mouseEntered(MouseEvent e) {
            	deleteButton.setCursor(new Cursor(Cursor.HAND_CURSOR));

            }

            public void mouseExited(MouseEvent e) {
            	deleteButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }
        });
        
        uploadButton.addMouseListener(new MouseAdapter() {
        	public void mouseClicked(MouseEvent mouseEvent) {
        		try {
					//outTransfer.sendFile(file, "attachment file", "questionRecord");
        			sendFile(outTransfer);
				} catch (XMPPException e) {
					e.printStackTrace();
				}
            }
        	
            public void mouseEntered(MouseEvent e) {
            	uploadButton.setCursor(new Cursor(Cursor.HAND_CURSOR));

            }

            public void mouseExited(MouseEvent e) {
            	uploadButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }
        });
        
        String fileName = this.fileToSend.getName();
        long fileSize = this.fileToSend.length();
        ByteFormat format = new ByteFormat();
        String text = format.format(fileSize);
        
        imageLabel.setFile(fileToSend);
        fileLabel.setText(fileName + " (" + text + ")");
        if (isImage(fileName)) {
            try {
                URL imageURL = this.fileToSend.toURL();
                ImageIcon image = new ImageIcon(imageURL);
                image = GraphicUtils.scaleImageIcon(image, 64, 64);
                imageLabel.setIcon(image);
            }
            catch (MalformedURLException e) {
                Log.error("Could not locate image.", e);
                imageLabel.setIcon(SparkRes.getImageIcon(SparkRes.DOCUMENT_INFO_32x32));
            }
        }
        else {
            File file1 = this.fileToSend;
            Icon icon = GraphicUtils.getIcon(file1);
            imageLabel.setIcon(icon);
        }
        
        makeClickable(imageLabel);

        setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.white));
    }
    
    public void sendFile(final OutgoingFileTransfer transfer) throws XMPPException{
    	transfer.sendFile(fileToSend, "attachment file", "questionRecord");
    	cancelButton.setVisible(true);
    	deleteButton.setVisible(false);
    	uploadButton.setVisible(false);
    	
    	long fileSize = transfer.getFileSize();
    	
    	cancelButton.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent mouseEvent) {
                transfer.cancel();
            }
        });

        cancelButton.addMouseListener(new MouseAdapter() {
            public void mouseEntered(MouseEvent e) {
                cancelButton.setCursor(new Cursor(Cursor.HAND_CURSOR));

            }

            public void mouseExited(MouseEvent e) {
                cancelButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }
        });
        
        progressBar.setMaximum((int)fileSize);
        progressBar.setVisible(false);
        progressBar.setStringPainted(true);
        add(progressBar, new GridBagConstraints(0, 3, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 150, 0));


        SwingWorker worker = new SwingWorker() {
            public Object construct() {
                while (true) {
                    try {
                        Thread.sleep(10);
                        FileTransfer.Status status = transfer.getStatus();
                        if (status == Status.error ||
                            status == Status.complete || status == Status.cancelled ||
                            status == Status.refused) {
                            break;
                        }
                        updateBar(transfer, nickname);
                    }
                    catch (InterruptedException e) {
                        Log.error("Unable to sleep thread.", e);
                    }

                }
                return "";
            }

            public void finished() {
                updateBar(transfer, nickname);
            }
        };

        worker.start();
    }


    private void makeClickable(final JLabel label) {
        label.setToolTipText(Res.getString("message.click.to.open"));

        label.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                openFile(fileToSend);
            }

            public void mouseEntered(MouseEvent e) {
                label.setCursor(new Cursor(Cursor.HAND_CURSOR));

            }

            public void mouseExited(MouseEvent e) {
                label.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }
        });
    }

    private void openFile(File downloadedFile) {
        try {
            if (!Spark.isMac()) {
                boolean opened = SparkManager.getNativeManager().openFile(downloadedFile);
                if (!opened) {
                    JOptionPane.showMessageDialog(this, Res.getString("title.error"), "No application associated with file type.", JOptionPane.ERROR_MESSAGE);
                }
            }
            else if (Spark.isMac()) {
                Runtime.getRuntime().exec("open " + downloadedFile.getCanonicalPath());
            }
        }
        catch (IOException e1) {
            Log.error("Exception occured while opening file.", e1);
        }
    }

    private void updateBar(final OutgoingFileTransfer transfer, String nickname) {
        FileTransfer.Status status = transfer.getStatus();
        if (status == Status.negotiating_stream) {
            titleLabel.setText(Res.getString("message.negotiation.file.transfer", nickname));
        }
        else if (status == Status.error) {
            if (transfer.getException() != null) {
                Log.error("Error occured during file transfer.", transfer.getException());
            }
            progressBar.setVisible(false);
            titleLabel.setText(Res.getString("message.unable.to.send.file", nickname));
            cancelButton.setVisible(false);
            retryButton.setVisible(true);
            showAlert(true);
        }
        else if (status == Status.in_progress) {
            showAlert(false);
            if (!progressBar.isVisible()) {
                progressBar.setVisible(true);
            }
            progressBar.setValue((int)transfer.getBytesSent());

            ByteFormat format = new ByteFormat();
            String bytesSent = format.format(transfer.getBytesSent());
            progressBar.setString(bytesSent + " sent");
        }
        else if (status == Status.complete) {
        	titleLabel.setVisible(true);
            titleLabel.setText("文件上传成功!");
            progressBar.setVisible(false);
            cancelButton.setVisible(false);
            showAlert(true);
        }
        else if (status == Status.cancelled) {
            progressBar.setVisible(false);
            titleLabel.setText(Res.getString("message.file.transfer.canceled"));
            cancelButton.setVisible(false);
            retryButton.setVisible(true);
            showAlert(true);
        }
        else if (status == Status.refused) {
            progressBar.setVisible(false);
            titleLabel.setText(Res.getString("message.file.transfer.rejected", nickname));
            cancelButton.setVisible(false);
            retryButton.setVisible(true);
            showAlert(true);
        }

    }

    private class TransferButton extends JButton {

        public TransferButton() {
            decorate();
        }

        /**
         * Create a new RolloverButton.
         *
         * @param text the button text.
         * @param icon the button icon.
         */
        public TransferButton(String text, Icon icon) {
            super(text, icon);
            decorate();
        }


        /**
         * Decorates the button with the approriate UI configurations.
         */
        private void decorate() {
            setBorderPainted(false);
            setOpaque(true);

            setContentAreaFilled(false);
            setMargin(new Insets(1, 1, 1, 1));
        }

    }


    private boolean isImage(String fileName) {
        fileName = fileName.toLowerCase();

        String[] imageTypes = {"jpeg", "gif", "jpg", "png"};
        for (String imageType : imageTypes) {
            if (fileName.endsWith(imageType)) {
                return true;
            }
        }

        return false;
    }

    private void showAlert(boolean alert) {
        if (alert) {
            titleLabel.setForeground(new Color(211, 174, 102));
            setBackground(new Color(250, 249, 242));
        }
        else {
            setBackground(new Color(239, 245, 250));
            titleLabel.setForeground(new Color(65, 139, 179));
        }
    }

    public void cancelTransfer() {
        if (transfer != null) {
            transfer.cancel();
        }
    }

}
